/*
 * 
 * 
 * @AUTHOR: Bade I. (c) 2009
 */

(function($){
	$.fn.spellcheck = function(options) {
		return this.each(function() {
			var $this = $(this);
			if ( !$this.is('[type=password]') && !$(this).data('schk') ) {
				$(this).data('schk', new $.SpellChecker(this, options));
			}
		});
	};

	$.fn.spellchecking = function() {
		return this.each(function() {
			var spellchecker = $(this).data('spellchecker');
			spellchecker && spellchecker.doSpellCheck();
		});
	};
	
	/*
	 * Configurable options.
	 * - lan: 		2 letter language code, default is english (en) 
	 * - events: 	space separated list of events that trigger spellcheck, default is 'keypress blur paste'
	 * - intv: 		Time interval in milliseconds to check spelling after a key event, default is 800 milliseconds.
	 * - url: 		url of the spellcheck service on your server, default is googlespell.php
	 * - cap: 		1 to ignore words with all caps, 0 to check them
	 * - dgt: 		1 to ignore words with digits, 0 to check them
	 */
	$.SpellChecker = function(elem, options) {
		this.$element = $(elem);
		this.options = $.extend({
				lan: 	'en',
				intv: 	800,
				events: 'keypress blur paste',
				url: 	'googlespell.php',
				cap: 	1,
				dgt: 	1
			}, options);
		this.bindEvents();
	};
	
	$.SpellChecker.prototype = {
		bindEvents: function() {
			if ( !this.options.events ) return;
			var ttl;
			var self = this;
			this.$element.bind(this.options.events, function(event) {
				if ( /^keypress|keyup|keydown/.test(event.type) ) {
					if ( ttl ) clearTimeout(ttl);
					ttl = setTimeout(function() { self.doSpellCheck(); }, self.options.intv);
				} else {
					self.doSpellCheck();
				}
			});
		},
		doSpellCheck: function() {
			var self = this;
			var prevText = this.text;
			var text = this.$element.val(); 
			if ( prevText === text ) return;
			this.text = this.$element.val();
			$.post(this.options.url, $.extend({ txt: this.text }, this.options), function(resp) { self.parseRes(resp); });
		},
		parseRes: function(results) {
			var self = this;
			this.results = [];
			$(results).find('c').each(function() {
				var $this = $(this),
				offset = $this.attr('o'),
				length = $this.attr('l');
				self.results.push({
					word: self.text.substr(offset, length),
					suggestions: $this.text().split(/\s/)
				});
			});
			this.showRes();
		},
		showRes: function() {
			$('#spellcheckres').remove();
			if ( !this.results.length ) return;
			var $container = $('<div id="spellcheckres"></div>').appendTo('body');
			var dl = [];
			var self = this;
			var offset = this.$element.offset();
			var height = this.$element[0].offsetHeight;
			var i, j;
			for (i = 0; i < this.results.length; i++) {
				var result = this.results[i];
				var suggestions = result.suggestions;
				dl.push('<dl><dt>'+result.word+'</dt>');
				for (j = 0; j < suggestions.length; j++)
					dl.push('<dd>'+suggestions[j]+'</dd>');
				dl.push('<dd class="ignore">ignore</dd></dl>');
			}
			$container.append(dl.join(''))
				.find('dd')
				.bind('click', function(event) {
					var $this = $(this);
					var $parent = $this.parent();
					if ( !$this.is('.ignore') )
						self.$element.val( self.$element.val().replace( $parent.find('dt').text(), $this.text() ) );
					$parent.remove();
					if ( $('#spellcheckres').is(':empty') )
						$('#spellcheckres').remove();
					this.blur();
				}).end().css({ top: offset.top + height, left: offset.left });
		}
	};
})(jQuery);